/*
 * 异常过滤器
 */

import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus, Logger } from '@nestjs/common'
import { Request, Response } from 'express'

@Catch()
// 统一错误返回格式
export class ExceptionsFilter implements ExceptionFilter {
  // constructor(private readonly loggingService: LoggingService) {}
  private readonly logger = new Logger(ExceptionsFilter.name)

  catch(exception: unknown, host: ArgumentsHost) {
    // * exception 当前正在处理的异常对象
    // * host 是传递给原始处理程序的参数的一个包装(Response/Request)的引用

    // 获取请求上下文
    const ctx = host.switchToHttp()
    const response = ctx.getResponse<Response>()
    const request = ctx.getRequest<Request>()

    // 访问文档不报错
    if (request.url === '/favicon.ico') {
      return
    }

    const errorResponse = this.getErrorResponse(exception, request)
    const status = errorResponse.code

    this.logError(exception, request, status)
    response.status(HttpStatus.OK).json(errorResponse)
  }

  private getErrorResponse(exception: unknown, request: Request): ApiResponseData<null> {
    let status: number
    let message: string = '内部服务器错误'
    let error: string | undefined

    if (exception instanceof CustomExceptionFilter) {
      status = exception.getStatus()
      message = exception.message
      error = exception.name
    }
    else if (exception instanceof HttpException) {
      status = exception.getStatus()
      const response = exception.getResponse()
      switch (typeof response) {
        case 'string':
          message = response
          break
        default:
          message = (response as any).message || message
          error = (response as any).error
          break
      }
    }
    else if (exception instanceof Error) {
      // 处理特定错误类型
      switch (error) {
        case 'PrismaClientKnownRequestError':
          status = HttpStatus.BAD_REQUEST
          break
        default:
          status = HttpStatus.INTERNAL_SERVER_ERROR
          message = exception.message
          break
      }
    }

    return {
      path: request.url,
      code: status,
      msg: message,
      error,
    }
  }

  private logError(exception: unknown, request: Request, _status: number) {
    let errorMessage = ''
    let stack = ''

    if (exception instanceof HttpException) {
      errorMessage = `${exception.getStatus()} - ${exception.message}`
      stack = (exception as any).stack || ''
    }
    else if (exception instanceof Error) {
      errorMessage = `${exception.name} - ${exception.message}`
      stack = exception.stack || ''
    }
    else {
      errorMessage = `Unknown error: ${JSON.stringify(exception)}`
    }
    // 打印错误摘要
    this.logger.error(`❌ Error occurred: ${errorMessage}`)

    // 打印完整请求上下文
    this.logger.error(
      `📌 Request details: ${JSON.stringify(
        {
          method: request.method,
          url: request.url,
          body: request.body,
          query: request.query,
          params: request.params,
        },
        null,
        2,
      )}`,
    )

    // 打印堆栈信息
    if (stack) {
      this.logger.error(`🧵 Stack trace:\n${stack}`)
    }

    // if (status >= 500) {
    //   this.logger.error(
    //     `Request details: ${JSON.stringify({
    //       method: request.method,
    //       url: request.url,
    //       body: request.body,
    //       query: request.query,
    //       params: request.params,
    //     })}`,
    //   );
    // }
  }
}

export class CustomExceptionFilter extends HttpException {
  constructor(message: string, status: HttpStatus) {
    super({ message, status }, status)
  }
}
